<template>
  <div
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
    style="width: 100%"
    v-if="!initializing"
    class="vc-component"
    :style="visual.parseStyle(currNode.currStyle)"
  >
    <el-popover
      ref="popoverRef"
      :width="popoverWidth"
      placement="bottom-start"
      :fallback-placements="['bottom', 'right', 'left', 'top']"
      :visible-arrow="true"
      trigger="click"
    >
      <template #reference>
        <el-input
          v-if="inputDisabled"
          disabled
          v-model="message"
        />
        <el-input
          v-else
          ref="messageRef"
          v-model="message"
          :placeholder="placeholder"
          @click="messageClick"
          @input="messageChange"
        >
          <template #suffix>
            <cc-icon
              v-if="hovering"
              style="cursor: pointer;color: #c0c4cc"
              @click.stop="clearInput"
              iconId="018dca412c4ebd53fd1d"
            />
          </template>
        </el-input>
      </template>
      <el-row v-if="multiple" style="text-align: center;padding-top: 10px;">
        <el-button
          style="width: 100%"
          class="el-button--primary"
          @click="confirm"
        >确定</el-button>
      </el-row>
      <el-input v-model="filterText" style="margin: 8px 0" placeholder="输入查询" />
      <el-scrollbar
        wrap-class="popover-scrollbar"
        wrap-style="min-height:0px;max-height: 400px;"
        view-style="height:100%;"
        v-loading="loading"
        element-loading-text="数据加载中..."
        :noresize="false"
      >
        <el-row class="tree-row">
          <el-tree
            style="width: 100%"
            ref="tree"
            node-key="id"
            :data="treeData"
            :props="treeProps"
            :highlight-current="true"
            :default-expanded-keys="expandedData"
            :filter-node-method="filterNode"
            :expand-on-click-node="true"
            :show-checkbox="multiple"
            @node-expand="nodeExpand"
            @node-click="nodeClick"
          >
            <template v-slot="{ data }">
              <div class="node-item">
                <span class="node-label" :title="data.text"><span>{{data.text}}</span></span>
              </div>
            </template>
          </el-tree>
        </el-row>
      </el-scrollbar>
    </el-popover>
  </div>
</template>

<script setup>
import { ref, watch, inject, getCurrentInstance, onMounted, nextTick } from 'vue';
import { getOrganization } from '@/utils/system';
import { useDisabled, useFormItem } from 'element-plus';
import visual from "@/visual/js/visual";
import EventHandler from "@/visual/js/event";

const emit = defineEmits(['change']);
const props = defineProps({
  node: Object
});
const initializing = ref(true);
const pageData = inject("pageData", ref({}));
const currNode = ref(props.node);
const inputDisabled = useDisabled();
const formItem = useFormItem();
const multiple = ref(false);
const tree = ref();
const filterText = ref('');
const message = ref('');
const loading = ref(false);
const selectedData = ref([]);
const expandedData = ref([]);
const treeData = ref([]);
const treeProps = ref({
  children: "children",
  label: function (data) {
    return data.text;
  }
});
const hovering = ref(false);
const messageRef = ref();
const popoverRef = ref();
const popoverWidth = ref('-');

const placeholder = ref('');
const clearable = ref(false);
const eventHandler = new EventHandler(
  inject('eventHandler', Function, true),
  getCurrentInstance(),
  currNode.value
);

const init = (styleId) => {
  initializing.value = true;
  visual.initStyle(currNode.value, styleId);
  const compStyle = currNode.value.currCompStyle || {};
  multiple.value = compStyle['multiple'] === true;
  placeholder.value = compStyle['placeholder'] || '--请选择--';
  clearable.value = compStyle['clearable'] || false;
  nextTick(() => initializing.value = false);
};

const loadValue = async() => {
  const dataList = (await visual.loadData(currNode.value.compData, eventHandler, getData(), currNode.value)).data || [];
  const value = dataList.length > 0 && dataList[0]['内容'] || '';
  selectedData.value = value ? value.split(',') : [];
  pageData.value[currNode.value.name] = value;
  calcValue();
};

const clearInput = () => {
  changeValue('', '');
};

const messageClick = () => {
  tree.value.filter('');
  const width = messageRef.value.$el.getBoundingClientRect().width;
  if (width && width > 0) {
    popoverWidth.value = width < 300 ? 300 : width;
  }
  return false;
};

const messageChange = () => {
  tree.value.filter(message.value);
};

const confirm = () => {
  let nodes = tree.value.getCheckedNodes();
  let multipleValue = [];
  let multipleMessage = [];
  nodes.forEach((item) => {
    if (!item.disable && item.data && item.data.type === '4') {
      multipleValue.push(item.id);
      multipleMessage.push(item.data.name);
    }
  });

  tree.value.setCheckedKeys(multipleValue);
  selectedData.value = multipleValue;
  pageData.value[currNode.value.name] = multipleValue.join(',');
  message.value = multipleMessage.join(',');
  filterText.value = '';
  popoverRef.value && popoverRef.value.hide()
  emit('change');

  nextTick(() => {
    initializing.value = false;
    if (formItem && formItem.formItem) {
      formItem.formItem.validate('change');
    }
  });
};

const changeValue = (id, value) => {
  initializing.value = true;
  tree.value.setChecked(id);
  selectedData.value = [id];
  pageData.value[currNode.value.name] = id;
  message.value = value;
  filterText.value = '';
  emit('change');

  nextTick(() => {
    initializing.value = false;
    if (formItem && formItem.formItem) {
      formItem.formItem.validate('change');
    }
  });
};

const filterNode = (value, data) => {
  if (!value) return true;
  return data.text.indexOf(value) >= 0;
};

const nodeExpand = () => {
  setTimeout(() => {
    popoverRef.value && popoverRef.value.popperRef.popperInstanceRef.forceUpdate();
  }, 300);
};

const nodeClick = (data) => {
  if (data.disabled === true || multiple.value) return;
  if (data?.data?.type === '4') {
    changeValue(data.id || '', data.text || '');
  }
};

const loadTree = async () => {
  treeData.value = await getOrganization();
  if (treeData.value && treeData.value.length === 1) {
    expandedData.value = [treeData.value[0].id];
  }
  calcValue();
};

const calcValue = () => {
  if (selectedData.value
      && selectedData.value.length > 0
      && treeData.value
      && treeData.value.length > 0) {
    const list = findData(treeData.value, selectedData.value);
    if (list && list.length > 0) {
      for (let i = 0; i < list.length; i++) {
        message.value = list[i].text;
      }
    } else {
      message.value = '';
    }
  } else {
    message.value = '';
  }
};

const findData = (list, ids) => {
  let results = [];
  if (list === undefined || list == null || ids === undefined || ids == null) {
    return results;
  }

  for (let i = 0; i < list.length; i++) {
    const id = list[i].id + '';
    if (id !== '0' && ids.indexOf(id) >= 0) {
      results.push(list[i]);
    }

    if (list[i].children !== undefined && list[i].children != null) {
      results = results.concat(findData(list[i].children, ids));
    }
  }

  return results;
};

watch(() => filterText.value, (newVal) => {
  tree.value.filter(newVal);
});

const getData = () => {
  return {
    inputParam: currNode.value.inputParam,
    value: pageData.value[currNode.value.name]
  };
};

const changeStyle = (styleId) => {
  init(styleId);
};

const refresh = async() => {
  initializing.value = true;
  await loadValue();
  await nextTick(() => initializing.value = false);
};

onMounted(async() => {
  await loadTree();
  await init();
  await loadValue();
  await eventHandler.trigger('初始化事件');
});

defineExpose({ getData, changeStyle, refresh });
</script>